using Consul;
using hao_Common.Consul.Options;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace hao_Common.Consul.Services
{
    /// <summary>
    /// Consul 服务注册实现类
    /// 负责与 Consul 服务器交互，执行服务注册、注销和查询操作
    /// </summary>
    public class ConsulServiceRegistry : IConsulServiceRegistry
    {
        /// <summary>
        /// Consul 客户端，用于与 Consul 服务器通信
        /// </summary>
        private readonly IConsulClient _consulClient;
        
        /// <summary>
        /// Consul 配置选项
        /// </summary>
        private readonly ConsulOptions _consulOptions;
        
        /// <summary>
        /// 日志记录器
        /// </summary>
        private readonly ILogger<ConsulServiceRegistry> _logger;
        
        /// <summary>
        /// 当前服务实例的唯一标识符
        /// 在注册时生成，注销时使用
        /// </summary>
        private string? _serviceId;

        /// <summary>
        /// 构造函数
        /// 通过依赖注入获取所需的服务
        /// </summary>
        /// <param name="consulClient">Consul 客户端</param>
        /// <param name="consulOptions">Consul 配置选项</param>
        /// <param name="logger">日志记录器</param>
        public ConsulServiceRegistry(
            IConsulClient consulClient,
            IOptions<ConsulOptions> consulOptions,
            ILogger<ConsulServiceRegistry> logger)
        {
            _consulClient = consulClient;
            _consulOptions = consulOptions.Value;
            _logger = logger;
        }

        /// <summary>
        /// 异步注册服务到 Consul
        /// 创建服务注册信息并提交到 Consul 服务器
        /// </summary>
        /// <returns>注册成功返回 true，失败返回 false</returns>
        public async Task<bool> RegisterServiceAsync()
        {
            try
            {
                var registration = _consulOptions.ServiceRegistration;
                
                // 生成服务唯一标识符
                // 如果配置中未指定 ServiceId，则自动生成
                _serviceId = string.IsNullOrEmpty(registration.ServiceId) 
                    ? $"{registration.ServiceName}-{registration.ServiceAddress}-{registration.ServicePort}"
                    : registration.ServiceId;

                // 创建 Consul 服务注册对象
                var serviceRegistration = new AgentServiceRegistration
                {
                    ID = _serviceId,                           // 服务唯一标识
                    Name = registration.ServiceName,           // 服务名称
                    Address = registration.ServiceAddress,     // 服务地址
                    Port = registration.ServicePort,           // 服务端口
                    Tags = registration.Tags,                  // 服务标签
                    Check = new AgentServiceCheck              // 健康检查配置
                    {
                        HTTP = registration.HealthCheckUrl,                                    // 健康检查 URL
                        Interval = TimeSpan.FromSeconds(registration.HealthCheckInterval),     // 检查间隔
                        Timeout = TimeSpan.FromSeconds(registration.HealthCheckTimeout),      // 检查超时
                        DeregisterCriticalServiceAfter = TimeSpan.FromMinutes(1)              // 失败后自动注销时间
                    }
                };

                // 向 Consul 提交服务注册请求
                var result = await _consulClient.Agent.ServiceRegister(serviceRegistration);
                
                // 检查注册结果
                if (result.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    _logger.LogInformation("Service {ServiceName} registered successfully with ID: {ServiceId}", 
                        registration.ServiceName, _serviceId);
                    return true;
                }
                
                _logger.LogError("Failed to register service {ServiceName}. Status: {StatusCode}", 
                    registration.ServiceName, result.StatusCode);
                return false;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error registering service to Consul");
                return false;
            }
        }

        /// <summary>
        /// 异步从 Consul 注销服务
        /// 根据服务 ID 从 Consul 中移除服务注册信息
        /// </summary>
        /// <returns>注销成功返回 true，失败返回 false</returns>
        public async Task<bool> DeregisterServiceAsync()
        {
            try
            {
                // 检查服务 ID 是否有效
                if (string.IsNullOrEmpty(_serviceId))
                {
                    _logger.LogWarning("Service ID is null or empty, cannot deregister");
                    return false;
                }

                // 向 Consul 提交服务注销请求
                var result = await _consulClient.Agent.ServiceDeregister(_serviceId);
                
                // 检查注销结果
                if (result.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    _logger.LogInformation("Service {ServiceId} deregistered successfully", _serviceId);
                    return true;
                }
                
                _logger.LogError("Failed to deregister service {ServiceId}. Status: {StatusCode}", 
                    _serviceId, result.StatusCode);
                return false;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error deregistering service from Consul");
                return false;
            }
        }

        /// <summary>
        /// 异步获取指定服务的所有实例
        /// 从 Consul 健康检查 API 获取服务实例列表（包括不健康的实例）
        /// </summary>
        /// <param name="serviceName">服务名称</param>
        /// <returns>服务实例列表</returns>
        public async Task<List<ServiceEntry>> GetServicesAsync(string serviceName)
        {
            try
            {
                // 调用 Consul Health API 获取服务实例
                var result = await _consulClient.Health.Service(serviceName);
                return result.Response?.ToList() ?? new List<ServiceEntry>();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting services for {ServiceName}", serviceName);
                return new List<ServiceEntry>();
            }
        }

        /// <summary>
        /// 异步获取指定服务的健康实例
        /// 从 Consul 健康检查 API 获取通过健康检查的服务实例列表
        /// </summary>
        /// <param name="serviceName">服务名称</param>
        /// <returns>健康的服务实例列表</returns>
        public async Task<List<ServiceEntry>> GetHealthyServicesAsync(string serviceName)
        {
            try
            {
                // 调用 Consul Health API，第三个参数 true 表示只返回健康的实例
                var result = await _consulClient.Health.Service(serviceName, string.Empty, true);
                return result.Response?.ToList() ?? new List<ServiceEntry>();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting healthy services for {ServiceName}", serviceName);
                return new List<ServiceEntry>();
            }
        }
    }
}